home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / dism.arc / DIS86.DOC next >
Text File  |  1991-06-13  |  21KB  |  597 lines

  1.                          dis86 - Interactive 8086 Disassembler
  2.  
  3.    (C) COPYRIGHT 1985, 86 by James R. Van Zandt,  ALL RIGHTS RESERVED
  4.  
  5.  
  6.  
  7.  
  8. You are encouraged to copy and distribute this program freely, provided:
  9.  
  10.     1)    No fee is charged beyond the actual cost for such copying and
  11.         distribution.
  12.  
  13.     2)    It is distributed ONLY in its original, unmodified state.
  14.  
  15. If you like this program, and find it of use, then your contribution will
  16. be appreciated.  A current version program disk and printed documentation are
  17. available if you send $50 to:
  18.  
  19.             James R. Van Zandt
  20.             27 Spencer Dr.
  21.             Nashua NH 03062
  22.  
  23. SYNOPSIS
  24.  
  25. Dis86 is a full-screen, interactive disassembler of object code for
  26. the 8086, 8087, 8088, 80186, 80286, and 80386 (products of Intel), and 
  27. the V20 and V30 (products of NEC).  The 80386 disassemblies include 32 
  28. bit operands and addresses.  Dis86 implements the concept of a "current 
  29. location: and allows use of the cursor keys to change it.  Code can come 
  30. from a .EXE file (in which case the header is properly interpreted), any 
  31. other file (assumed to have no header), or anywhere in main memory 
  32. (0000:0000 - F000:FFFF).  Dis86 can install changes, even in a .EXE 
  33. file, making it a convenient way to install patches.  Versions are 
  34. available for the IBM PC (and clones) and Z-100.
  35.  
  36.  
  37. STARTING THE DISASSEMBLER
  38.  
  39. To disassemble a file, give the file name (optionally preceded by a path 
  40. name) on the command line:
  41.  
  42.         A>dis86 foo.exe
  43.  
  44. To disassemble from RAM, use an empty command line:
  45.  
  46.         A>dis86
  47.  
  48. There are no command line switches.
  49.  
  50.  
  51. FILE HEADER INFORMATION
  52.  
  53. For a .EXE file, the information in the file header will be displayed 
  54. when the program is first run and in response to the H command (see 
  55. below).
  56.  
  57.  
  58. DISPLAY SCREEN
  59.  
  60. During disassembly, the screen will resemble the following:
  61.  
  62.         0000:0100      e9 01 90            jmp            9104
  63.         0000:0103      55                  push           bp       
  64.         0000:0104      8b ec               mov            bp,sp    
  65.         0000:0106      83 ec 0e            sub            sp,0e    
  66.         
  67.                                   ...
  68.         
  69.         0000:012C      50                  push           ax         
  70.         0000:012D      b8 69 00            mov            ax,0069    
  71.         0000:0130      50                  push           ax         
  72.         0000:0131      e8 e9 5c            call           5e1d       
  73.         dis86 1.00 - A SHAREWARE software product  (c) 1986, James R. Van Zandt
  74.         >
  75.         ... 0000:0100  0000:0100  0000:0100  
  76.  
  77. Lines 1 through 21 are the disassembled code.  Each line starts with
  78. the current address, followed by the actual bytes being disassembled. 
  79. The rest of the line is the assembly language equivalent, if any, of
  80. the code.  The display for A (ASCII), B (byte), and D (data) formats is
  81. similar.  All numbers are shown in hexadecimal.
  82.  
  83. Line 22 is a message and prompt line showing, for example, the
  84. arguments needed for some commands.  Line 23 has the prompt.  Typed
  85. characters are echoed on the rest of this line.  Line 24 has three
  86. addresses, which are the first three entries in the stack (see the
  87. 'cursor right' and 'cursor left' commands below).
  88.  
  89.  
  90. CURSOR KEYS
  91.  
  92. The "current location" is the address displayed on the first line
  93. of disassembly.  The cursor keys are used to adjust the current 
  94. location.
  95.  
  96. The up and down cursor keys (8 and 2 on the numeric pad) are used to
  97. move the current location a small amount (note that they are not
  98. inverses):
  99.  
  100.         <up>     moves up by one byte (lower address)
  101.         <down>   moves down by one line (higher address)
  102.  
  103.  
  104. The <pg up> and <pg dn> keys (9 and 3 on the numeric pad) move the
  105. current location by larger amounts.  In C (code) format, they move by
  106. 32 bytes.  In the other formats, they move by 11 lines on the screen. 
  107. They will not move the cursor out of the disassembly buffer. 
  108. Otherwise, they are inverses.:
  109.  
  110.         <pg up>   moves up by 32 bytes (lower address)
  111.         <pg dn>   moves down by 32 bytes (higher address)
  112.  
  113.  
  114. The above keys change only the current location.  Other commands change 
  115. the current location by potentially large amounts, but first save it in 
  116. a stack.  The first three addresses in the stack are shown on the 
  117. command line at the bottom of the screen.
  118.  
  119. If the instruction at the current location is a jump, call, or a
  120. reference to a data location, the cursor right key (6 on the numeric pad)
  121. will push the current location on the stack and go to the referenced
  122. location.  For a data reference, the disassembly format is changed to D
  123. (hex and ASCII).
  124.  
  125.         <right>   follows a jump, call, or data reference
  126.  
  127.  
  128. The cursor left or left arrow key (4 on the numeric pad) will pop the
  129. last address off the stack.  Note that right arrow followed by left
  130. arrow will return you to the same address, whereas left arrow
  131. (returning, let us say, to address X) followed by right arrow will only
  132. return you to the same address if there is an appropriate jump or call
  133. at X.
  134.  
  135.         <left>    pops address stack
  136.  
  137. Aûfter using the right arrow or one of the commands A, B, C, D, or G (in
  138. next section) to go to a new address, and using the left arrow key to
  139. pop the stack, you will sometimes want to return to the previous
  140. address.  The stack no longer holds the address.  However, the left
  141. arrow key saves the current location in a special "previous state"
  142. before popping the stack.
  143.  
  144. To return to the address stored in the "previous state", type shift
  145. right arrow on a Z-100, or control right arrow on an IBM PC.
  146.  
  147.         <shift><right>   returns to "previous state"   (Z-100)
  148.         <cntrl><right>   returns to "previous state"   (IBM)
  149.  
  150.  
  151. In summary, the unshifted keys on the numeric pad are:
  152.  
  153. <home> top of file          ^   up 1 byte         <pg up>  up 32 bytes 
  154.                             |         
  155.  
  156. <--    pop addr stack                             -->      follow jump/call
  157.  
  158.                             |         
  159. <end>  end of file          v  down 1 line        <pg dn>  down 32 bytes  
  160.  
  161.  
  162. <ins>  setup options 
  163.  
  164. On the Z-100, the four keys with arrows on them may be used in addition
  165. to the 2, 4, 6, and 8 on the numeric pad.
  166.  
  167.  
  168. LETTER COMMANDS FOR MOVING THE CURSOR
  169.  
  170. There are five letter commands to change the display format and/or
  171. disassembly address:
  172.  
  173.     A    ASCII data
  174.     B    byte data (hex)
  175.     D    data (both hex bytes and ASCII)
  176.     C    code
  177.     G    goto
  178.  
  179. These commands may be in upper or lower case.  Each may be followed by:
  180.  
  181.     <ret>        Only the display format changes.
  182.  
  183.     A <expression> <ret>
  184.             The current location changes to the specified address.
  185.  
  186.     S <expression> <expression> <expression> <ret>
  187.             The disassembler searches from the current
  188.             address to the end of the buffer for the
  189.             specified sequence of hex bytes.  If an
  190.             expression has a segment specified using the
  191.             ':' operator (below), the segment is ignored.
  192.  
  193.     S T [string] <ret>
  194.             The disassembler searches from the current
  195.             address to the end of the buffer for the
  196.             specified ASCII string.  Cases are not
  197.             distinct, and the high order bit is ignored. 
  198.             The string can also be introduced by a double
  199.             quote.
  200.  
  201.     S R <expression> <ret>
  202.             The disassembler searches from the current
  203.             address to the end of the buffer for a
  204.             reference (jump or call) to the specified
  205.             address.
  206.  
  207. An <expression> can involve any of these items:
  208.  
  209.     hex numbers    (either upper or lower case letters)
  210.     cs, ds, es, ss, fs, gs
  211.             currently assumed segment register values
  212.     $        current location
  213.     @        offset of top address on the stack
  214.     'x'        single characters
  215.     "jkl;"        multiple character strings
  216.  
  217. ...and any of these operators:
  218.  
  219.     + - * /        add, subtract, multiply, divide
  220.     :        separate segment and offset
  221.  
  222. Note that G with no address is a noop.  There are two ways to ask for a string
  223. search.  For example,
  224.  
  225.     S T jones
  226.  
  227.     S "Jones"
  228.  
  229. In the first search, cases are not distinct and the high order bit
  230. is ignored.  In the second search, the high order bit must be 0 and
  231. the cases must match.
  232.  
  233.  
  234. OPTIONS
  235.  
  236. The 'O' command or <ins> (0 on the numeric pad) brings up menus for
  237. changing setup options and allows the user to reset the disassembly
  238. window.  Use <space> or <ins> to move to the next screen, or <esc> to
  239. return to disassembly.
  240.  
  241. In the first options menu, use the right and left cursor keys or <ret>
  242. to change the entries.  The first item shows the processor which is
  243. supposed to execute the code being disassembled.  There is some
  244. conflict in op codes between the V20 and V30 on one hand and the 80286
  245. and 80386 on the other.  That is, the two families use the same op
  246. codes for different instructions.  Dis86 selects the instruction
  247. appropriate for the chip shown in this menu.  In addition, instructions
  248. not implemented by the indicated chip will be flagged.  The other item
  249. on the first menu lets the user specify 16 or 32 bit mode for the
  250. 80386.  In the 16 bit mode the 80386 is similar to the 8086.  In the 32
  251. bit mode arithmetic is performed in 32 bit registers and all address
  252. offsets are 32 bits.  (The 80386 itself selects the mode based on a bit
  253. in the segment table entry for the code segment.)
  254.  
  255. In the second options menu, change an entry by typing over it.  The two
  256. items are the byte value which matches anything in a byte or character
  257. search (the "wild card" byte) and the number of bytes displayed on each
  258. line for the A, B, or D formats.  The latter value can also be set
  259. using the W command.
  260.  
  261. The last options display is a small map of the code being disassembled
  262. which will resemble the following:
  263.  
  264.         ds= -10
  265.         cs=0000
  266.         |                  ss=0960
  267.         es= -10            |
  268.         | cursor=0000:0453 |
  269.         CCCCCCCCCCCCCCcccccccccccccc
  270.         ^0000:0000
  271.                      ^0000:6144
  272.  
  273. The Cs represent the code being disassembled.  The capital Cs are the
  274. portion of code in the disassembly window (see discussion below).  The
  275. assumed values for the segment registers, the current location (labeled
  276. "cursor"), and the beginning and end addresses of the disassembly
  277. window are also shown.  The window can be adjusted using the right and
  278. left cursor keys.
  279.  
  280. By using the <ins> key to enter the options menu and to step from one
  281. menu to the next, you can leave your right hand on the numeric pad.
  282.  
  283.  
  284. MISCELLANEOUS COMMANDS
  285.  
  286. The 'P' command is used to print a disassembly listing to a file.  The
  287. first time this command is used, it prompts for a file name.  The
  288. default file name is "printout".  To actually send the listing to a
  289. printer, specify the filename "prn".  If the file already exists the
  290. new information will be appended.  The file is automatically closed
  291. before the disassembler exits.  The command also prompts for the
  292. beginning and end addresses of the code to be printed.  The default
  293. addresses print the current screen.  When the printing is finished, the
  294. current address is advanced to the first byte not printed.  Thus, you
  295. can repeat the sequence
  296.  
  297.         P <ret> <ret>
  298.  
  299. to print a large section.
  300.  
  301. Enter 'R' to display and/or change the assumed segment register values.
  302. Entries may be full expressions.  For example, to copy the value from SS 
  303. into DS, use the cursor keys to select the DS register and type
  304.  
  305.         ss <ret>
  306.  
  307.  
  308. The 'S' command selects a new segment register value for displaying 
  309. addresses.  The new register is shown on the message line.  The actual 
  310. address being disassembled is not changed (see "segmentation" below).
  311.  
  312. The 'W' command is used to set the number of bytes displayed on each
  313. line for the A, B, and D formats.  This is useful for displaying
  314. tables.  For example, when dis86 is executed without a file, it
  315. displays bytes starting at address 0000:0000 and the width is set to
  316. four so each interrupt vector is shown on a separate line.
  317.  
  318. Type '?' to get a series of help screens.  Type <esc> to return to the
  319. disassembly, or any other key to advance to the next screen
  320.  
  321. The 'E' command allows the user to modify the program being
  322. disassembled.  Changes are initially made only in the disassembly
  323. buffer.  Before the buffer is overwritten or the disassembler
  324. terminates, the user is asked whether the changes are to be written to
  325. the file or RAM area being disassembled.  The values entered may be
  326. given in hex expressions or ASCII.  Values too large to fit into a byte
  327. are assumed to be words or double words.  Here are some examples:
  328.  
  329.     45 67 'A'            =>  45 67 41
  330.  
  331.     2ea+3                =>  ed 02
  332.  
  333.     9c/3                 =>  34
  334.  
  335.     "Alpha Beta" 0d 0a   =>  41 6c 70 68 61 20 42 65 74 61 0d 0a
  336.  
  337.  
  338. Enter 'Q' to stop the disassembler and return to DOS.
  339.  
  340.  
  341. TYPING REQUESTED DATA
  342.  
  343. Many commands supply default entries for requested data.  If you decide
  344. to accept the default, just enter <ret>.  For editing entries,
  345. you can position the cursor using the left and right cursor keys to
  346. move by one character, <home> (7 on the numeric pad) to move to the
  347. left end of the string, or <end> (1 on the numeric pad) to move to the
  348. right end.  Use the <del> or <backspace> keys to delete incorrect
  349. characters, or just type characters to be inserted.  (There is no
  350. "replace" typing mode.) In every case but one, you can also edit the
  351. default entry by making <right>, <end>, or <del> your first keystroke. 
  352. The exception is the default for the byte search function.
  353.  
  354.  
  355. DISASSEMBLY WINDOW
  356.  
  357. The disassembler uses a buffer to hold the code being disassembled. 
  358. For most purposes, this disassembly window is transparent to the user. 
  359. If the user requests an address within the file but outside the
  360. disassembly window, the appropriate code is automatically read in.  The
  361. existence of the window is apparent in only three cases: 
  362.  
  363.     1.    If the disassembler is started near the end of the window 
  364.         and reaches the end before it fills the screen, the
  365.         rest of the screen will be left blank.
  366.  
  367.     2.    The searches are done only from the current location to the
  368.         end of the buffer.
  369.  
  370.     3.    If the contents of the buffer has been changed (see 'E'
  371.         command) the user is asked whether they should be
  372.         written out before the buffer is overwritten or control 
  373.         is returned to DOS.
  374.  
  375.  
  376. LOAD ADDRESS
  377.  
  378. Code from a .COM file is displayed as though its Program Segment Prefix
  379. were at 0000:0000 and its load address were 0000:0100.
  380.  
  381. Code from a .EXE file is displayed as though its load address were
  382. 0000:0000.  This puts its Program Segment Prefix is 10 paragraphs or
  383. 100 (hex) bytes lower.  This is somewhat awkward, because the DS and ES
  384. registers are initialized to point to the PSP.  The disassembler
  385. displays this segment value as -10.  The advantage of a load address of
  386. 0000:0000 is that no relocation is necessary.  The bytes displayed are
  387. exactly the same as those in the file.  This also means that the code
  388. can be modified (see below for the 'E' command) and written back to the
  389. file without being "unrelocated".
  390.  
  391.  
  392. SEGMENTATION
  393.  
  394. Addresses are displayed in segment:offset form, using the current
  395. assumed value of the current segment register.  The current segment 
  396. register can be selected using the 'S' command to step among the 
  397. available registers (CS, SS, DS, ES, FS, and GS - the last two only with 
  398. 80386 code).  Changing segment registers or their values does not move 
  399. the disassembler cursor.  Only the displayed segment and offset values 
  400. will change to reflect the new assumptions.  A legal offset will be
  401. displayed as a four digit hex number (0000 to FFFF).  Other offsets
  402. (negative, or greater than 64K) will also be calculated and displayed
  403. correctly, although they are illegal on the 8086.  Illegal offsets will
  404. have more than four digits.  
  405.  
  406. The segment register values are initialized as indicated in the file 
  407. header (for .EXE files) or to zero (for other files or RAM).  The 
  408. disassembler has no way of determining the values which may be set 
  409. during execution.  For example, the initialization code for DeSmet C 
  410. programs reset DS to the same value as the initial SS before executing 
  411. main().
  412.  
  413. The assumed segment register values can be altered in two ways.  Any 
  414. segment register can be changed using the register menu reached by the 
  415. 'R' command.  In addition, when the right arrow key is used to follow a 
  416. far call or jump, the new code segment value is loaded into the CS 
  417. register.  When the user specifies a new segment value on an A, B, C, D, 
  418. or G command, that value is used for subsequent displays but none of the 
  419. assumed segment register values is changed.
  420.  
  421. The segmentation models of the protected modes of the 80286 and 80386 
  422. are not supported.
  423.  
  424.  
  425. ALIGNMENT
  426.  
  427. Dis86 will correctly disassemble code if started on the first byte of an 
  428. instruction.  If started in the middle of an instruction, it will 
  429. disassemble that instruction and perhaps several more incorrectly.  In 
  430. this case the disassembler is said to be out of alignment with the 
  431. object code.  The disassembler will tend to correct its alignment if it 
  432. continues long enough.  8086 instructions tend to be longer than, for 
  433. example, those for the 8080, so the disassembler will tend to stay out 
  434. of alignment for more bytes.  Generally speaking, the alignment will be 
  435. correct after the first half dozen lines.
  436.  
  437.  
  438. SUMMARY
  439.  
  440. Here are all the letter commands:
  441.  
  442. A nnnn      ASCII data
  443. B nnnn      byte date (hex)
  444. C nnnn      code (disassembly)
  445. D nnnn      data (hex and ASCII)
  446. E           enter new data (follow with a series of hex expressions)
  447.  
  448. G nnnn      goto address nnnn
  449. H           display file header information (for .EXE files only)
  450. O           change setup options
  451. P           print disassembly listing to file
  452. Q           quit to DOS
  453.  
  454. R           change segment register values
  455. S           select a new segment register
  456. W           set bytes of data per line for A, B, and D formats
  457. X           exchange current address (at top of screen) with top of stack
  458. ?           display help screens
  459.  
  460.  
  461. EXAMPLE 1
  462.  
  463. In the examples, <left>, <right>, <up>, and <down> refer to the four
  464. cursor keys (4, 6, 8, and 2 on the numeric pad, plus the four arrow
  465. keys on the Z-100 keyboard).  <pg up> and <pg dn> refer to the 9 and 3
  466. on the numeric pad.
  467.  
  468. To investigate the bootstrap code, type
  469.  
  470.     A>dis86 <ret>
  471.  
  472. and press
  473.  
  474.     <space>
  475.  
  476. to advance to the disassembly display, which will be a D (data) format 
  477. display of the interrupt vectors.  Next type
  478.  
  479.     c a ffff:0000 <ret>
  480.  
  481. (for Code format at the Address ffff:0000).  On an IBM, the ROM release 
  482. date and machine ID appear in the last 16 bytes of the ROM.  To see 
  483. them, type
  484.  
  485.     D <ret>
  486.  
  487. The release data is at addresses ffff:0005 - ffff:000c in ASCII.  The 
  488. machine ID is at ffff:000e.  Some of the possible values are:
  489.  
  490.     ff    IBM PC
  491.     fe    IBM XT and Portable IBM PC
  492.     fd    IBM PCjr
  493.     fc    IBM AT
  494.     2d    Compaq
  495.     9a    Compaq-Plus
  496.  
  497. Return to code format by typing
  498.  
  499.     C <ret>
  500.  
  501. One of the instructions displayed will almost certainly be a jump.  If 
  502. so, press
  503.  
  504.     <down>
  505.  
  506. enough times to bring the jump to the top line, then
  507.  
  508.     <right>
  509.  
  510. to follow the jump.  Note that the previous addresses were pushed onto 
  511. the stack, as shown on the bottom line.  To return to the most recent 
  512. address, press
  513.  
  514.     <left>
  515.  
  516. To leave the disassembler, press
  517.  
  518.     Q
  519.  
  520.  
  521. EXAMPLE 2
  522.  
  523. For a second example, let us disassemble the disassembler itself.  Begin 
  524. by typing
  525.  
  526.     A>dis86 dis86.exe <ret>
  527.  
  528. Note the header information, including the entry point of 0000:0000 and 
  529. the initial stack location of approximately 09e0:9eb8.  Proceed to the 
  530. disassembly screen by typing
  531.  
  532.     <space>
  533.  
  534. The disassembler starts in C (code) format at the entry point, which is 
  535. a jump to the initialization code.  To follow the jump, type
  536.  
  537.     <right>
  538.  
  539. One of the early instructions in the initialization code refers to the 
  540. first location in the stack segment.  Bring this location to the top of 
  541. the screen by typing
  542.  
  543.     <pg dn> <down> <down>
  544.  
  545. and follow the reference by typing
  546.  
  547.     <right>
  548.  
  549. Since it was a data reference, the disassembler automatically switched 
  550. to D (data) format.  Also, the addresses are displayed using the value 
  551. of segment register SS.  Note that the two previous addresses have been 
  552. pushed onto the stack, as shown at the bottom of the screen.  Return to 
  553. the most recent one by typing
  554.  
  555.     <left>
  556.  
  557. The initialization code gets rather involved, but one of its functions
  558. is to initialize DS to the same value as SS.  To reflect this, use the
  559. R command:
  560.  
  561.     R
  562.  
  563. DS is the first register in the list, so you need only enter the 
  564. appropriate value:
  565.  
  566.     ss <ret> <space>
  567.  
  568. The code for the main program immediately followed the jump at 
  569. 0000:0000.  To return there, type
  570.  
  571.     <left>
  572.  
  573. Send a copy of this screen to the file "printout" by typing
  574.  
  575.     P <ret> <ret> <ret>
  576.  
  577. To inspect the data segment, type
  578.  
  579.     A ds:0 <ret>
  580.  
  581. To display more characters on each line, use the W command:
  582.  
  583.     W 60 <ret>
  584.  
  585. Use the search command to find one of the messages:
  586.  
  587.     G S T hime <ret>
  588.  
  589. This string won't be found.  To correct the spelling to "home" and try 
  590. again, type
  591.  
  592.     G S T <right> o <del> <ret>
  593.  
  594. Once again, leave the disassembler by pressing
  595.  
  596.     Q
  597.